package com.zookeeper.swing;

import com.cmd.dos.hw.util.CMDUtil;
import com.common.dict.Constant2;
import com.common.thread.ThreadPoolUtil;
import com.common.util.SystemHWUtil;
import com.common.util.WindowUtil;
import com.io.hw.file.util.FileUtils;
import com.io.hw.json.HWJacksonUtils;
import com.string.widget.util.RegexUtil;
import com.string.widget.util.ValueWidget;
import com.swing.component.AssistPopupTextArea;
import com.swing.component.AssistPopupTextField;
import com.swing.dialog.DialogUtil;
import com.swing.dialog.GenericFrame;
import com.swing.dialog.toast.ToastMessage;
import com.swing.event.EventHWUtil;
import com.swing.menu.MenuCallback2;
import com.swing.menu.MenuDto;
import com.swing.menu.MenuUtil2;
import com.swing.menu.TableInfo;
import com.swing.messagebox.GUIUtil23;
import com.swing.table.MyButtonEditor;
import com.swing.table.MyButtonRender;
import com.swing.table.TableUtil3;
import com.zookeeper.ConfigInfo;
import com.zookeeper.ZkConnect;
import com.zookeeper.component.DelButton;
import com.zookeeper.component.EditButton;
import com.zookeeper.component.EnterDirectoryBtn;
import com.zookeeper.dialog.ConfigDialog;
import com.zookeeper.event.listener.ZkModifyListener;
import com.zookeeper.listener.MenuBarListener;
import com.zookeeper.util.ZkOperateUtil;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class ZkEditorApp extends GenericFrame {

    private JPanel contentPane;
    private AssistPopupTextField keyTextField;
    private AssistPopupTextField valTextField;
    private ZooKeeper zk;
    private ZkConnect zkConnect;
    private JCheckBox inteCheckBox;
    private JCheckBox testCheckBox;
    private AssistPopupTextField searchTextField;
    private JTable zkNodeTable;
    static final String[] columnNames = {"参数名", "参数值(字符串)", "操作", "操作", "操作"};
    private Map<String, String> resultMap;
    private JLabel statusLabel;
    private ConfigInfo configInfo = new ConfigInfo();
    /***
     * 模糊查询
     */
    private JCheckBox fuzzyCheckBox;
    /***
     * 配置文件路径
     */
    public static final String configFilePath = System.getProperty("user.home") + File.separator + ".zookeeper_clientEditer.properties";
    /***
     * 配置文件
     */
    private File configFile;
    private AssistPopupTextField currentPathtextField;
    private JCheckBox needPrefixCheckbox;
    private AssistPopupTextArea resultTextArea;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ZkEditorApp frame = new ZkEditorApp();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public ZkEditorApp() {
        setTitle("zookeeper 编辑器");
        try {
            setIcon("/img/logo.jpg", this.getClass());
        } catch (IOException e) {
            e.printStackTrace();
        }

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//        setBounds(100, 100, 650, 300);
        fullScreen2(this);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JSplitPane splitPane = new JSplitPane();
        splitPane.setDividerLocation(300);
        contentPane.add(splitPane, BorderLayout.CENTER);

        JPanel panel = new JPanel();
        splitPane.setLeftComponent(panel);
        GridBagLayout gbl_panel = new GridBagLayout();
        gbl_panel.columnWidths = new int[]{0, 0, 0, 0};
        gbl_panel.rowHeights = new int[]{0, 0, 0, 0, 0, 0};
        gbl_panel.columnWeights = new double[]{0.0, 1.0, 1.0, Double.MIN_VALUE};
        gbl_panel.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, 1.0, Double.MIN_VALUE};
        panel.setLayout(gbl_panel);

        JLabel lblKey = new JLabel("key");
        GridBagConstraints gbc_lblKey = new GridBagConstraints();
        gbc_lblKey.insets = new Insets(0, 0, 5, 5);
        gbc_lblKey.anchor = GridBagConstraints.EAST;
        gbc_lblKey.gridx = 1;
        gbc_lblKey.gridy = 0;
        panel.add(lblKey, gbc_lblKey);

        keyTextField = new AssistPopupTextField();
        keyTextField.setText("");
        keyTextField.placeHolder("HOST_EE");
        GridBagConstraints gbc_keyTextField = new GridBagConstraints();
        gbc_keyTextField.insets = new Insets(0, 0, 5, 0);
        gbc_keyTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_keyTextField.gridx = 2;
        gbc_keyTextField.gridy = 0;
        panel.add(keyTextField, gbc_keyTextField);
        keyTextField.setColumns(10);

        JLabel lblValue = new JLabel("value");
        GridBagConstraints gbc_lblValue = new GridBagConstraints();
        gbc_lblValue.anchor = GridBagConstraints.EAST;
        gbc_lblValue.insets = new Insets(0, 0, 5, 5);
        gbc_lblValue.gridx = 1;
        gbc_lblValue.gridy = 1;
        panel.add(lblValue, gbc_lblValue);

        valTextField = new AssistPopupTextField();
        valTextField.placeHolder("不必用双引号括起来");
        GridBagConstraints gbc_valTextField = new GridBagConstraints();
        gbc_valTextField.insets = new Insets(0, 0, 5, 0);
        gbc_valTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_valTextField.gridx = 2;
        gbc_valTextField.gridy = 1;
        panel.add(valTextField, gbc_valTextField);
        valTextField.setColumns(10);

        JPanel panel_2 = new JPanel();
        GridBagConstraints gbc_panel_2 = new GridBagConstraints();
        gbc_panel_2.insets = new Insets(0, 0, 5, 0);
        gbc_panel_2.gridwidth = 2;
        gbc_panel_2.fill = GridBagConstraints.BOTH;
        gbc_panel_2.gridx = 1;
        gbc_panel_2.gridy = 2;
        panel.add(panel_2, gbc_panel_2);

//		JCheckBox onlinehCeckBox = new JCheckBox("线上");
//		panel_2.add(onlinehCeckBox);


//        panel_2.add(testCheckBox);

        JPanel panel_3 = new JPanel();
        GridBagConstraints gbc_panel_3 = new GridBagConstraints();
        gbc_panel_3.insets = new Insets(0, 0, 5, 0);
        gbc_panel_3.gridwidth = 2;
        gbc_panel_3.fill = GridBagConstraints.BOTH;
        gbc_panel_3.gridx = 1;
        gbc_panel_3.gridy = 3;
        panel.add(panel_3, gbc_panel_3);

        JButton btnUpdate = new JButton("update");
        btnUpdate.addActionListener((e) -> {
            if (check()) return;
            String path = configInfo.getZkRootPath();
            updateZkNode(path);
        });
        panel_3.add(btnUpdate);

        JButton btnAdd = new JButton("add");
        btnAdd.addActionListener((e) -> {
            if (check()) return;
            String path = configInfo.getZkRootPath();
            createZkNode(path);
            return;
        });
        panel_3.add(btnAdd);

        JScrollPane scrollPane_1 = new JScrollPane();
        GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
        gbc_scrollPane_1.gridwidth = 2;
        gbc_scrollPane_1.insets = new Insets(0, 0, 0, 5);
        gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
        gbc_scrollPane_1.gridx = 1;
        gbc_scrollPane_1.gridy = 4;
        panel.add(scrollPane_1, gbc_scrollPane_1);

        resultTextArea = new AssistPopupTextArea();
        resultTextArea.setLineWrap(true);
        resultTextArea.setWrapStyleWord(true);
        scrollPane_1.setViewportView(resultTextArea);

        JPanel panel_1 = new JPanel();
        splitPane.setRightComponent(panel_1);
        GridBagLayout gbl_panel_1 = new GridBagLayout();
        gbl_panel_1.columnWidths = new int[]{0, 0, 0, 0};
        gbl_panel_1.rowHeights = new int[]{0, 0, 0, 0, 0};
        gbl_panel_1.columnWeights = new double[]{1.0, 0.0, 0.0, Double.MIN_VALUE};
        gbl_panel_1.rowWeights = new double[]{0.0, 1.0, 0.0, 0.0, Double.MIN_VALUE};
        panel_1.setLayout(gbl_panel_1);

        searchTextField = new AssistPopupTextField();
        searchTextField.placeHolder("输入关键字搜索");
        searchTextField.setToolTipText("输入关键字搜索");
        GridBagConstraints gbc_searchTextField = new GridBagConstraints();
        gbc_searchTextField.insets = new Insets(0, 0, 5, 5);
        gbc_searchTextField.fill = GridBagConstraints.HORIZONTAL;
        gbc_searchTextField.gridx = 0;
        gbc_searchTextField.gridy = 0;
        panel_1.add(searchTextField, gbc_searchTextField);
        searchTextField.setColumns(10);
        searchTextField.addActionListener((ActionEvent e) -> {
            searchAction();
            ToastMessage.toast("查询完成", 1000);
        });

        fuzzyCheckBox = new JCheckBox("模糊查询");
        fuzzyCheckBox.addChangeListener((ChangeEvent e) -> {
            searchTextField.requestFocus();
        });
        GridBagConstraints gbc_checkBox = new GridBagConstraints();
        gbc_checkBox.insets = new Insets(0, 0, 5, 5);
        gbc_checkBox.gridx = 1;
        gbc_checkBox.gridy = 0;
        panel_1.add(fuzzyCheckBox, gbc_checkBox);

        JButton btnSearch = new JButton("search");
        GridBagConstraints gbc_btnSearch = new GridBagConstraints();
        gbc_btnSearch.insets = new Insets(0, 0, 5, 0);
        gbc_btnSearch.gridx = 2;
        gbc_btnSearch.gridy = 0;
        panel_1.add(btnSearch, gbc_btnSearch);
        btnSearch.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                searchAction();
            }
        });

        JScrollPane scrollPane = new JScrollPane();
        GridBagConstraints gbc_scrollPane = new GridBagConstraints();
        gbc_scrollPane.insets = new Insets(0, 0, 0, 5);
        gbc_scrollPane.gridwidth = 3;
        gbc_scrollPane.fill = GridBagConstraints.BOTH;
        gbc_scrollPane.gridx = 0;
        gbc_scrollPane.gridy = 1;
        panel_1.add(scrollPane, gbc_scrollPane);

        zkNodeTable = new JTable();
        scrollPane.setViewportView(zkNodeTable);
        rendTable2(zkNodeTable, null);//表格绑定鼠标事件
        JPanel panel_5 = new JPanel();
        GridBagConstraints gbc_panel_5 = new GridBagConstraints();
        gbc_panel_5.anchor = GridBagConstraints.WEST;
        gbc_panel_5.gridwidth = 3;
        gbc_panel_5.insets = new Insets(0, 0, 5, 0);
        gbc_panel_5.fill = GridBagConstraints.VERTICAL;
        gbc_panel_5.gridx = 0;
        gbc_panel_5.gridy = 2;
        panel_1.add(panel_5, gbc_panel_5);

        statusLabel = new JLabel("");
        panel_5.add(statusLabel);

        JPanel panel_4 = new JPanel();
        GridBagConstraints gbc_panel_4 = new GridBagConstraints();
        gbc_panel_4.gridwidth = 3;
        gbc_panel_4.fill = GridBagConstraints.BOTH;
        gbc_panel_4.gridx = 0;
        gbc_panel_4.gridy = 3;
        panel_1.add(panel_4, gbc_panel_4);

        needPrefixCheckbox = new JCheckBox("需要前缀名");
        panel_4.add(needPrefixCheckbox);

        JButton exportBtton = new JButton("复制到剪切板");
        exportBtton.addActionListener((ActionEvent e) -> {
            String exportResult = exportZKNode(needPrefixCheckbox.isSelected());
            WindowUtil.setSysClipboardText(exportResult);
            ToastMessage.toast("已复制到剪切板", 2000);
        });
        panel_4.add(exportBtton);

        JPanel panel_6 = new JPanel();
        FlowLayout flowLayout = (FlowLayout) panel_6.getLayout();
        flowLayout.setAlignment(FlowLayout.LEFT);
        contentPane.add(panel_6, BorderLayout.NORTH);

        JLabel label = new JLabel("当前路径:");
        panel_6.add(label);

        currentPathtextField = new AssistPopupTextField();
        currentPathtextField.addFocusListener(new FocusListener() {
            private long lastTime = 0;

            @Override
            public void focusGained(FocusEvent e) {
                System.out.println("focusGained :");
                // 节流,throttle
                long delta = System.currentTimeMillis() - lastTime;
                System.out.println("focusGained delta :" + delta);
                if (lastTime != 0
                        && delta < 10000) {//10 second
                    lastTime = System.currentTimeMillis();
                    return;
                }
                lastTime = System.currentTimeMillis();
                searchAction(false);
            }

            @Override
            public void focusLost(FocusEvent e) {

            }
        });
        currentPathtextField.addActionListener(e -> {
            System.out.println("addActionListener :");
            searchAction(false);
        });
        currentPathtextField.setEditable(false);
        panel_6.add(currentPathtextField);
        currentPathtextField.setColumns(40);

        JButton backBtn = new JButton("回到上一级");
        backBtn.addActionListener((ActionEvent e) -> {
            String orginRoot = configInfo.getZkRootPath();
//                System.out.println("orginRoot :" + orginRoot);
            if (orginRoot != null && !orginRoot.equals(Constant2.SLASH)) {
                configInfo.setZkRootPath(SystemHWUtil.getParentDir(orginRoot));
            }
            if (null == orginRoot) {
                configInfo.setZkRootPath(Constant2.SLASH);
            }
            refreshCurrentPath();
            searchAction(true);
        });
        panel_6.add(backBtn);

        JButton backToRootBtn = new JButton("回到根目录");
        backToRootBtn.addActionListener(e -> {
            configInfo.setZkRootPath(Constant2.SLASH);
            refreshCurrentPath();
            searchAction(true);
        });
        panel_6.add(backToRootBtn);

        try {
            readConfig();//必须在connectServer()方法之前
        } catch (IOException e) {
            e.printStackTrace();
            ToastMessage.toast("读取配置文件失败", 2000, Color.red);
        }

        setMenuBar2();
        ThreadPoolUtil.execute(() -> {
            try {
                connectServer();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        try {
            init33(this, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        addGlobalKey();
        refreshCurrentPath();

        new ZkModifyListener(resultTextArea);
    }

    public void refreshCurrentPath() {
        currentPathtextField.setText(getRootPath());
    }

    public String exportZKNode(boolean needPrefix) {
        StringBuffer stringBuffer = new StringBuffer();
        if (null == resultMap) {
            searchAction();
        }
        Set<String> keys = resultMap.keySet();
        String path = getRootPath();
        for (String key : keys) {
            Object[] objs = new Object[2];
            objs[0] = key;
            if (needPrefix) {
                stringBuffer.append(path);
            }
            stringBuffer.append(key).append("=");
            stringBuffer.append(resultMap.get(key)).append(SystemHWUtil.CRLF);
        }
//        System.out.println(" :" +stringBuffer);
        return stringBuffer.toString();
    }

    public void searchAction() {
        searchAction(false);
    }

    public void searchAction(boolean ignoreKeyword) {
        System.out.println(" search");
        if (searchTextField == null) {
            exitAction();
        }
        String searchKeyWord = searchTextField.getText2().trim();
        String path = getRootPath();
        if (ignoreKeyword) {
            searchKeyWord = null;
        }
        setTableData2(searchKeyWord, path);
//        refreshCurrentPath();
    }

    private void exitAction() {
        dispose();
        System.exit(0);
    }

    public String getRootPath() {
        String path = ZkConnect.rootPath;

        if (!ValueWidget.isNullOrEmpty(this.configInfo.getZkRootPath())) {
            path = this.configInfo.getZkRootPath();
        }
        return path;
    }

    public void setTableData2(String searchKeyWord, String path) {
        statusLabel.setText("");
        TableUtil3.setTableData2(zkNodeTable, new Object[0][], columnNames);
        try {
            resultMap = zkConnect.search(path, zk);
            if (ValueWidget.isNullOrEmpty(resultMap)) {
                ToastMessage.toast("暂无数据:" + path, 2000, Color.RED);
                return;
            }

//            System.out.println("map :" + resultMap);
            Object[][] datas = null;
            if (ValueWidget.isNullOrEmpty(searchKeyWord)) {
                datas = parseTableDate(resultMap);
            } else {
                if (fuzzyCheckBox.isSelected()) {
                    Map<String, String> filteMap = new TreeMap<>();
                    Set<String> keys = resultMap.keySet();
                    for (String key : keys) {
                        if (key.contains(searchKeyWord) || RegexUtil.contain2(key, searchKeyWord)) {
                            filteMap.put(key, resultMap.get(key));
                        }
                    }
                    datas = parseTableDate(filteMap);
                } else {
                    datas = accurateQuery(searchKeyWord);
                }
            }
            statusLabel.setText("结果: 共" + datas.length + " 条数据");
            TableUtil3.setTableData2(zkNodeTable, datas, columnNames);
            rendTable();
        } catch (KeeperException e1) {
            e1.printStackTrace();
            GUIUtil23.errorDialog(e1);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
            GUIUtil23.errorDialog(e1);
        }
    }

    public Object[][] accurateQuery(String searchKeyWord) {
        Object[][] datas;
        String searchVal = resultMap.get(searchKeyWord);
        if (searchVal == null) {
            searchVal = "没有找到";
            ToastMessage.toast("没有找到:" + searchKeyWord, 2000, Color.red);
        } else {
            searchVal = "\"" + searchVal + "\"";
        }
        datas = new Object[1][];
        Object[] objs = new Object[5];
        objs[0] = searchKeyWord;
        objs[1] = searchVal;
        addOperateBtn(searchKeyWord, objs, searchVal);
        datas[0] = objs;
        return datas;
    }

    /***
     * 刷新表格
     */
    public void repaintTable() {
        zkNodeTable.repaint();
    }

    /***
     * setCellEditor and setCellRenderer
     */
    public void rendTable() {

        this.zkNodeTable.getColumnModel().getColumn(2)
                .setCellEditor(new MyButtonEditor());
        this.zkNodeTable.getColumnModel().getColumn(2)
                .setCellRenderer(new MyButtonRender());

        this.zkNodeTable.getColumnModel().getColumn(3)
                .setCellEditor(new MyButtonEditor());
        this.zkNodeTable.getColumnModel().getColumn(3)
                .setCellRenderer(new MyButtonRender());

        this.zkNodeTable.getColumnModel().getColumn(4)
                .setCellEditor(new MyButtonEditor());
        this.zkNodeTable.getColumnModel().getColumn(4)
                .setCellRenderer(new MyButtonRender());

        repaintTable();//单元格更新access_token 后,需要更新单元格
    }

    public Object[][] parseTableDate(Map<String, String> map) {
        Set<String> keys = map.keySet();
        Object[][] datas = new Object[keys.size()][];
        int index = 0;
        for (String key : keys) {
            Object[] objs = new Object[5];
            objs[0] = key;
            String nodeVal = map.get(key);
            objs[1] = "\"" + nodeVal + "\"";
            addOperateBtn(key, objs, nodeVal);

            datas[index] = objs;
            index++;
        }
        return datas;
    }

    public void addOperateBtn(String key, Object[] objs, String nodeVal) {
        objs[2] = new DelButton(key) {
            @Override
            public void callback() {
                super.callback();
                searchAction();
            }
        }.setZkConnect(zkConnect).setRootPath(getRootPath());

        objs[3] = new EditButton(key) {
            @Override
            public void action(String nodeKey) {
                keyTextField.setText(getNodeKey());
                valTextField.setText(getNodeValue());
            }
        }.setNodeValue(nodeVal);

        objs[4] = new EnterDirectoryBtn(key) {
            @Override
            public void action(String nodeKey) {
                enterDirectory(nodeKey);
            }


        }.setRootPath(getRootPath());
    }

    private void enterDirectory(String nodeKey) {
        configInfo.setZkRootPath(getRootPath() + nodeKey);
        refreshCurrentPath();
        searchAction(true);
    }

    public boolean check() {
        if (!DialogUtil.verifyTFEmpty(keyTextField, "键")) {
            return true;
        }
        if (!DialogUtil.verifyTFEmpty(valTextField, "键值")) {
            return true;
        }
        return false;
    }

    public void updateZkNode(String rootPath) {
        try {
            String oldVal = zkConnect.updateNode(rootPath + keyTextField.getText2(), valTextField.getText());
            ZkConnect.clearCache(rootPath);
            ToastMessage.toast("更新成功,原值:" + oldVal, 2000);
        } catch (Exception e1) {
            e1.printStackTrace();
            ToastMessage.toast("请确认该节点是否已经存在", 3000, Color.red);
        }
    }

    public void createZkNode(String rootPath) {
        try {
            zkConnect.createNode(rootPath + keyTextField.getText2(), valTextField.getText());
            ZkConnect.clearCache(rootPath);
            ToastMessage.toast("添加成功", 2000);
        } catch (Exception e1) {
            e1.printStackTrace();
            ToastMessage.toast(e1.getMessage(), 2000, Color.RED);
        }
    }

    /***
     * 连接zk
     * @throws Exception
     */
    public void connectServer() throws Exception {
        if (ValueWidget.isNullOrEmpty(this.configInfo.getIps())) {
            GUIUtil23.warningDialog("请进入菜单\"File|配置\" 设置服务器地址");
            return;
        }
        zkConnect = new ZkConnect();//172.17.200.12:2181
        /*ZooKeeper zk = */
        Integer port = null;
        if (!ValueWidget.isNullOrEmpty(this.configInfo.getPort())) {
            port = Integer.parseInt(this.configInfo.getPort());
        }

        zkConnect.connect(this.configInfo.getIps(), port);

//        zkConnect = ZkConnect.connect();
        zk = zkConnect.getZk();
    }

    /***
     * 只有子类调用了GenericFrame.init33() 方法,beforeDispose() 才会被调用
     */
    @Override
    public void beforeDispose() {
        super.beforeDispose();
        closeZk();
        saveConfig();
    }

    public void closeZk() {
        if (null != zk) try {
            zk.close();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /***
     * 读取配置文件
     * @throws IOException
     */
    private void readConfig() throws IOException {
        configFile = new File(configFilePath);
        if (!configFile.exists()) {
            configFile = new File(".zookeeper_clientEditer.properties");
        }
        if (!configFile.exists()) {
            return;
        }
        InputStream inStream = new FileInputStream(configFile);
        String resumeInput = FileUtils.getFullContent4(inStream, SystemHWUtil.CHARSET_UTF);
        inStream.close();//及时关闭资源
        this.configInfo = (ConfigInfo) HWJacksonUtils.deSerialize(resumeInput, ConfigInfo.class);
        if (this.configInfo == null) {
            this.configInfo = new ConfigInfo();
        }
    }

    private void setMenuBar2() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileM = new JMenu("File");
        JMenuItem configItem = new JMenuItem("配置");
        JMenuItem connectItem = new JMenuItem("重新连接");
        configItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                showConfig();
                refreshCurrentPath();
            }
        });

        connectItem.addActionListener((ActionEvent e) -> {
                /*int result = JOptionPane.showConfirmDialog(null, "确认要重新连接吗 ?", "确认",
                        JOptionPane.OK_CANCEL_OPTION);
                if (result == JOptionPane.OK_OPTION) {*/
            closeZk();//先关闭连接,再创建新的连接
            try {
                connectServer();
                ToastMessage.toast("连接成功", 1000);
            } catch (Exception e1) {
                e1.printStackTrace();
                ToastMessage.toast("连接失败", 1000, Color.red);
            }
        });
        fileM.add(configItem);
        JMenuItem exportCacheItem = new JMenuItem("导出缓存");
        exportCacheItem.addActionListener((e) -> {
            Map<String, Map<String, String>> searchResultCacheMap = ZkConnect.getSearchResultCacheMap();
            StringBuilder stringBuilder = new StringBuilder();
            searchResultCacheMap.forEach((k1, values) -> {
                stringBuilder.append(k1).append(":--------------").append(SystemHWUtil.CRLF);
                values.forEach((key, value) -> {
                    stringBuilder.append(key).append("=").append(value).append(SystemHWUtil.CRLF);
                });
                stringBuilder.append("------------- end -------------").append(SystemHWUtil.CRLF).append(SystemHWUtil.CRLF);
            });
            System.out.println(" :");
            WindowUtil.setSysClipboardText(stringBuilder.toString());
            ToastMessage.toastRight("已复制到剪切板", 1000);
        });
        fileM.add(exportCacheItem);

        menuBar.add(fileM);

        MenuBarListener menuBarListener = new MenuBarListener(configInfo);
        JMenu cleanCacheM = new JMenu("清除缓存");
        JMenuItem cleanAllItem = new JMenuItem("清除全部");
        cleanAllItem.addActionListener(menuBarListener);
        JMenuItem cleanOneItemItem = new JMenuItem("清除当前路径");
        cleanOneItemItem.addActionListener(menuBarListener);

        cleanCacheM.add(cleanAllItem);
        cleanCacheM.add(cleanOneItemItem);

        menuBar.add(cleanCacheM);
//        menuBar.add(configItem);
        menuBar.add(connectItem);
        setJMenuBar(menuBar);
    }

    public void showConfig() {
        new ConfigDialog(ZkEditorApp.this.configInfo).setVisible(true);
    }

    /***
     * 增加全局快捷键Shift+Tab<br>
     * Ctrl+Shift+X
     */
    private void addGlobalKey() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        // 注册应用程序全局键盘事件, 所有的键盘事件都会被此事件监听器处理.
        toolkit.addAWTEventListener(
                (event) -> {
                    if (event.getClass() != KeyEvent.class) {
                        return;
                    }
                    KeyEvent kE = ((KeyEvent) event);
                    if (kE.getKeyCode() == KeyEvent.VK_K/*Ctrl +K*/
                            && (kE.isControlDown() || kE.isMetaDown())
                            && kE.getID() == KeyEvent.KEY_PRESSED) {
                        searchTextField.requestFocus();
                        searchTextField.selectAll();
                    } else if ((kE.getKeyCode() == KeyEvent.VK_COMMA) && (!((InputEvent) event)//显示配置面板,mac :command;window:ctrl
                            .isShiftDown()) && (EventHWUtil.isControlDown((InputEvent) event) || ((InputEvent) event).isControlDown()) && kE.getID() == KeyEvent.KEY_PRESSED) {//Ctrl+H
                        showConfig();
                    }
                }, java.awt.AWTEvent.KEY_EVENT_MASK);
    }

    @Override
    public void saveConfig() {
        System.out.println("saveConfig :");
        configFile = new File(configFilePath);
        if (!configFile.exists()) {
            try {
                SystemHWUtil.createEmptyFile(configFile);
            } catch (IOException e) {
                e.printStackTrace();
                GUIUtil23.errorDialog(e);
            }
        }
        CMDUtil.show(configFilePath);//因为隐藏文件是只读的
        //处理
        System.out.println("保存文件:" + configFilePath);
        if (null == configFile) {
            System.out.println("configFile is null");
            exitAction();
        }
        String content = HWJacksonUtils.getJsonP(this.configInfo);
        if (ValueWidget.isNullOrEmpty(content)
                || content.length() < 20) {
            String msg = "要保存的内容太小,不保存";
            System.out.println("msg :" + msg);
            return;
        }
        FileUtils.writeToFile(configFile, content, SystemHWUtil.CHARSET_UTF);
        CMDUtil.hide(configFilePath);
    }

    /***
     * 表格绑定鼠标事件
     * @param zkNodeTable
     */
    public void rendTable2(JTable zkNodeTable, JComponent target) {
        final MouseInputListener mouseInputListener = TableUtil3.getMouseInputListener(zkNodeTable,
                (JTable jTable, MouseEvent e, Object object) -> {
                    System.out.println("鼠标右键 :");
                    JPopupMenu popupmenu = new JPopupMenu();

                    MenuDto menuDto = buildMenuDto(/*zkNodeTable*/);//需要自己实现

                    MenuUtil2.buildPopupMenu(popupmenu, menuDto, zkNodeTable);
                    popupmenu.show(e.getComponent(), e.getX() + 15, e.getY());
                }
                , (JTable jTable, MouseEvent e, Object object) -> {
                    System.out.println("鼠标中键 ###");
                });
        if (null == target) {
            target = zkNodeTable;
        }
        target.addMouseListener(mouseInputListener);
    }

    /***
     * 右键菜单<br />
     * 构建菜单
     * @return
     */
    private MenuDto buildMenuDto(/*JTable jTable*/) {
        MenuDto menuDto = new MenuDto();

        String menuItemLabel = "查看值";
        MenuCallback2 callback2 = new MenuCallback2() {
            @Override
            public void actionPerformed(ActionEvent event, TableInfo tableInfo) {
                String nodeKey = (String) tableInfo.getjTable().getValueAt(tableInfo.getSelectedRow(), 0);
                String nodePath = getRootPath() + nodeKey;
                try {
                    String val = ZkConnect.getNodeValue(zk, nodePath);
                    GUIUtil23.infoDialog(val);
                    WindowUtil.setSysClipboardText(val);
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        menuDto.put(menuItemLabel, callback2);


        String enterMenuItemLabel = "进入目录";
        menuDto.put(enterMenuItemLabel, (event, tableInfo) -> {
            String nodeKey = (String) tableInfo.getjTable().getValueAt(tableInfo.getSelectedRow(), 0);
            enterDirectory(nodeKey);
        });


        String copyCellMenuItemLabel = "复制key";
        menuDto.put(copyCellMenuItemLabel, (event, tableInfo) -> {
            String nodeKey = (String) tableInfo.getjTable().getValueAt(tableInfo.getSelectedRow(), 0);
            ToastMessage.toastRight("复制成功:" + SystemHWUtil.splitAndFilterString(nodeKey, 30), 1000);
            WindowUtil.setSysClipboardText(nodeKey);
        });


        String copyValMenuItemLabel = "复制 val";
        menuDto.put(copyValMenuItemLabel, (event, tableInfo) -> {
            String nodeKey = (String) tableInfo.getjTable().getValueAt(tableInfo.getSelectedRow(), 1);
            ToastMessage.toastRight("复制成功:" + SystemHWUtil.splitAndFilterString(nodeKey, 30), 1000);
            WindowUtil.setSysClipboardText(nodeKey);
        });

        String deleteMenuItemLabel = "删除";
        menuDto.put(deleteMenuItemLabel, (ActionEvent event, TableInfo tableInfo) -> {
            String nodeKey = (String) tableInfo.getjTable().getValueAt(tableInfo.getSelectedRow(), 0);
            boolean success = ZkOperateUtil.deleteZkNode(nodeKey, getRootPath(), zkConnect);
            if (success) {
                searchAction(true);
            }
        });

        return menuDto;
    }
}

